package cn.udrm.water.base.v1.manager.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.udrm.water.base.v1.commons.models.ZTreeNodeVo;
import cn.udrm.water.base.v1.manager.cache.BaseOrganizationCache;
import cn.udrm.water.base.v1.manager.dto.BaseDepartmentDto;
import cn.udrm.water.base.v1.manager.dto.BaseDepartmentDtoMapper;
import cn.udrm.water.base.v1.manager.dto.BaseOrganizationDto;
import cn.udrm.water.base.v1.manager.dto.BaseOrganizationDtoMapper;
import cn.udrm.water.base.v1.manager.dto.BaseRoleDto;
import cn.udrm.water.base.v1.manager.dto.BaseRoleDtoMapper;
import cn.udrm.water.base.v1.manager.entities.BaseDepartment;
import cn.udrm.water.base.v1.manager.entities.BaseOrganization;
import cn.udrm.water.base.v1.manager.entities.BaseRole;
import cn.udrm.water.base.v1.manager.repository.BaseOrganizationRepository;

@Service
@Transactional(readOnly=true)
@CacheConfig(cacheNames="base_organizations")
public class BaseOrganizationService {
	
	@Autowired
	private BaseOrganizationRepository organizationRepository;
	@Autowired
	private BaseOrganizationCache organizationCache;
	@Autowired
	private BaseOrganizationDtoMapper organizationDtoMapper;
	@Autowired
	private BaseDepartmentDtoMapper departmentDtoMapper;
	@Autowired
	private BaseRoleDtoMapper roleDtoMapper;
	@Autowired
	private BaseDepartmentService departmentService;
	@Autowired
	private BaseRoleService roleService;
	
	/**
	 * 获取组织结构树（只获取角色）
	 * @return
	 */
	@Cacheable(key="methodName")
	public List<ZTreeNodeVo> getOrgZtreeOnlyRoles() {
		List<BaseOrganization> findAlls = organizationRepository.findAll();
		if (findAlls != null) {
			ArrayList<ZTreeNodeVo> list = new ArrayList<ZTreeNodeVo>();
			findAlls.forEach((org) -> {
				List<BaseRoleDto> roles = roleService.findByOrganizationId(org.getId());
				if (roles != null) {
					roles.forEach((role) -> {
						list.add(new ZTreeNodeVo(role.getId(), role.getName(), org.getId(), "ROLE"));
					});
				}
				list.add(new ZTreeNodeVo(org.getId(), org.getName(), "0", "ORGANIZATION"));
			});
			return list;
		}
		return null;
	}
	
	/**
	 * 获取组织机构树, 只获取第一层
	 * 组织机构下有部门和角色
	 * @return
	 */
	@Cacheable(key="methodName")
	public List<ZTreeNodeVo> getOrgZtree() {
		List<BaseOrganization> findAlls = organizationRepository.findAll();
		if (findAlls != null) {
			ArrayList<ZTreeNodeVo> list = new ArrayList<ZTreeNodeVo>();
			findAlls.forEach((org) -> {
				List<BaseDepartmentDto> departments = departmentService.findByOrganizationId(org.getId());
				List<BaseRoleDto> roles = roleService.findByOrganizationId(org.getId());
				if (departments != null) {
					departments.forEach((dept) -> {
						list.add(new ZTreeNodeVo(dept.getId(), dept.getName(), org.getId(), "DEPARTMENT"));
						List<BaseDepartmentDto> childrensDto = dept.getChildrensDto();
						if (childrensDto != null && childrensDto.size() != 0) {
							childrensDto.forEach((d) -> {
								list.add(new ZTreeNodeVo(d.getId(), d.getName(), dept.getId(), "DEPARTMENT"));
							});
						}
					});
				}
				if (roles != null) {
					roles.forEach((role) -> {
						list.add(new ZTreeNodeVo(role.getId(), role.getName(), org.getId(), "ROLE"));
					});
				}
				list.add(new ZTreeNodeVo(org.getId(), org.getName(), "0", "ORGANIZATION"));
			});
			return list;
		}
		return null;
	}
	
	@Cacheable(key="methodName+#p0")
	public BaseOrganizationDto getSelfById(String id) {
		BaseOrganization baseOrganization = organizationRepository.get(id);
		if (baseOrganization != null) {
			return organizationDtoMapper.from(baseOrganization);
		}
		return null;
	}
	
	/**
	 * 获取组织机构及其所有角色
	 * @param id
	 * @return
	 */
	@Cacheable(key="methodName+#p0")
	public BaseOrganizationDto findWithRolesById(String id) {
		BaseOrganization organization = organizationRepository.findWithRolesById(id);
		if (organization != null) {
			BaseOrganizationDto from = organizationDtoMapper.from(organization);
			List<BaseRole> roles = organization.getRoles();
			if (roles != null) {
				List<BaseRoleDto> list = roleDtoMapper.from(roles);
				from.setRoleDtos(list);
			}
			return from;
		}
		return null;
	}
	
	/**
	 * 获取组织机构及其所有部门
	 * @param id
	 * @return
	 */
	@Cacheable(key="methodName+#p0")
	public BaseOrganizationDto findWithDepartmentsById(String id) {
		BaseOrganization organization = organizationRepository.findWithDepartmentsById(id);
		if (organization != null) {
			BaseOrganizationDto from = organizationDtoMapper.from(organization);
			List<BaseDepartment> departments = organization.getDepartments();
			if (departments != null) {
				List<BaseDepartmentDto> list = departmentDtoMapper.from(departments);
				from.setDepartmentDtos(list);
			}
			return from;
		}
		return null;
	}
	
	@Cacheable(key="methodName+#p0")
	public BaseOrganizationDto get(String id) {
		BaseOrganization baseOrganization = organizationRepository.get(id);
		return organizationDtoMapper.from(baseOrganization);
	}

	@Transactional(readOnly=false)
	public BaseOrganizationDto save(BaseOrganizationDto organizationDto) {
		BaseOrganization baseOrganization = organizationDtoMapper.to(organizationDto);
		baseOrganization.setId(null);
		BaseOrganization saveAndFlush = organizationCache.saveAndFlush(baseOrganization);
		return organizationDtoMapper.from(saveAndFlush);
	}
	@Transactional(readOnly=false)
	public BaseOrganizationDto update(BaseOrganizationDto organizationDto) {
		BaseOrganization baseOrganization = organizationDtoMapper.to(organizationDto);
		BaseOrganization saveAndFlush = organizationCache.saveAndFlush(baseOrganization);
		return organizationDtoMapper.from(saveAndFlush);
	}
}
